package com.regent.central.bill.service.bean;

import com.github.pagehelper.PageHelper;
import com.regent.central.bill.common.SaleOrderType;
import com.regent.central.bill.core.CreateGoods;
import com.regent.central.bill.core.DeliveryGoods;
import com.regent.central.bill.core.SaleOrder;
import com.regent.central.bill.dto.delivery.DeliverySaleOrderDTO;
import com.regent.central.bill.dto.sale_order.*;
import com.regent.central.bill.repository.*;
import com.regent.central.bill.service.SaleOrderService;
import com.regent.central.infrastructure.service.bean.DomainServiceBean;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class SaleOrderServiceBean extends DomainServiceBean<SaleOrderMapper, SaleOrder> implements SaleOrderService {

    @Autowired
    private CreateGoodsMapper createGoodsMapper;

    @Autowired
    private ModifyGoodsMapper modifyGoodsMapper;

    @Autowired
    private ReturnGoodsMapper returnGoodsMapper;

    @Autowired
    private ClearanceMapper clearanceMapper;

    @Autowired
    private RemittanceMapper remittanceMapper;

    @Autowired
    private DeliveryGoodsMapper deliveryGoodsMapper;

    @Autowired
    private SaleOrderRemarkMapper saleOrderRemarkMapper;

    @Autowired
    private ReturnGoodsRemarkMapper returnGoodsRemarkMapper;

    @Autowired
    private CreateGoodsRemarkMapper createGoodsRemarkMapper;

    @Override
    public Integer getMaxOrderNoOfUnitIdAndOrderDay(String unitID, String orderDay) {
        return mapper.getMaxOrderNoOfUnitIdAndOrderDay(unitID, orderDay);
    }

    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
    public void setMerchandiser(String orderId, String merchandiserId) {
        mapper.setMerchandiser(orderId, merchandiserId);
    }

    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
    @Override
    public void setAddress(String orderId, String addressId) {
        mapper.setAddress(orderId, addressId);
    }

    public BigDecimal getLastPrice(String unitId, String goodsId, String customerId) {
        return mapper.getLastPrice(unitId, goodsId, customerId);
    }

    @Override
    public List<SaleOrderListDTO> getHistoryOrderList(String unitId, String customerId, String startSearchTime, int pageNo, int pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        List<String> historyOrderIds = mapper.getHistoryOrderIds(unitId, customerId, startSearchTime);
        if (historyOrderIds == null || historyOrderIds.isEmpty()) return Collections.emptyList();
        return mapper.getHistoryOrderList(historyOrderIds);
    }

    @Override
    public List<SaleOrderListDTO> getHistoryStyleOrderList(String unitId, String customerId, String startSearchTime, String styleId, int pageNo, int pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        List<String> historyOrderIds = mapper.getHistoryStyleOrderIds(unitId, customerId, startSearchTime, styleId);
        if (historyOrderIds == null || historyOrderIds.isEmpty()) return Collections.emptyList();
        List<SaleOrderListDTO> orders = mapper.getHistoryStyleOrderList(historyOrderIds, styleId);

        if (orders == null || orders.isEmpty()) return Collections.emptyList();

        Map<String, SaleOrderListDTO> map = orders.stream().collect(Collectors.toMap(SaleOrderListDTO::getSaleOrderId, order -> order));

        List<SaleOrderListDTO> deliveries = deliveryGoodsMapper.getSaleOrderStyleDeliveriesIn(styleId, map.keySet().toArray(new String[0]));
        deliveries.forEach(delivery -> {
            String saleOrderId = delivery.getSaleOrderId();
            SaleOrderListDTO order = map.get(saleOrderId);
            if (order == null) return;
            Map<String, SaleOrderListStyleDTO> styleMAP = order.getGoods().stream().collect(Collectors.toMap(SaleOrderListStyleDTO::getStyleId, style -> style));
            delivery.getGoods().forEach(goods -> {
                String styleID = goods.getStyleId();
                SaleOrderListStyleDTO style = styleMAP.get(styleID);
                if (style == null) return;
                Map<String, SaleOrderListStyleSKUDTO> skuMAP = style.getSkus().stream().collect(Collectors.toMap(SaleOrderListStyleSKUDTO::getSkuId, sku -> sku));
                goods.getSkus().forEach(sku -> {
                    String skuID = sku.getSkuId();
                    SaleOrderListStyleSKUDTO SKU = skuMAP.get(skuID);
                    BigDecimal delivered = SKU.getTotalDelivered();
                    delivered = delivered.add(sku.getQuantity());
                    SKU.setTotalDelivered(delivered);
                });
            });
        });

        orders.forEach(order -> order.getGoods().forEach(goods -> {
            Optional<BigDecimal> sum = goods.getSkus().stream().map(SaleOrderListStyleSKUDTO::getQuantity).reduce(BigDecimal::add);
            goods.setTotal(sum.orElse(BigDecimal.ZERO));
        }));

        return orders;
    }

    @Override
    public List<DeliverySaleOrderDTO> getOwedSaleOrders(
            String unitId,
            String customerId,
            String startSearchTime,
            String startTime,
            String endTime,
            String sortBy,
            Integer sortAs,
            String keyword,
            int pageNo,
            int pageSize
    ) {
        if (StringUtils.isBlank(customerId)) {
            PageHelper.startPage(pageNo, pageSize);
        }
        // 当前还欠货的销售单ID集合
        List<String> owedSaleOrderIds = mapper.getOwedSaleOrderIds(unitId, customerId, startSearchTime, startTime, endTime, sortBy, sortAs, keyword);
        if (owedSaleOrderIds == null || owedSaleOrderIds.isEmpty()) return Collections.emptyList();

        // 这些销售单的开单数量
        List<DeliverySaleOrderDTO> createdSaleOrders = mapper.getCreatedSaleOrders(owedSaleOrderIds, sortBy, sortAs);
        // 这些销售单的改单数量
        List<DeliverySaleOrderDTO> modifiedSaleOrders = mapper.getModifiedSaleOrders(owedSaleOrderIds);
        // 这些销售单的发货数量
        List<DeliverySaleOrderDTO> deliveredSaleOrders = mapper.getDeliveredSaleOrders(owedSaleOrderIds);
        // 公式 ∑（sku开单数） ± ∑（sku被改欠货数） - ∑（发货sku）
        Map<String, BigDecimal> modifieds = new HashMap<>();
        modifiedSaleOrders.forEach(modified -> modified.getStyles().forEach(style -> style.getSkus().forEach(
                sku -> {
                    String key = modified.getSaleOrderId() + "-" + style.getStyleId() + "-" + sku.getSkuId();
                    BigDecimal quantity = modifieds.get(key);
                    if (quantity != null) quantity = quantity.add(sku.getQuantity());
                    else quantity = sku.getQuantity();
                    modifieds.put(key, quantity);
                }))
        );

        Map<String, BigDecimal> delivereds = new HashMap<>();
        deliveredSaleOrders.forEach(delivered -> delivered.getStyles().forEach(style -> style.getSkus().forEach(
                sku -> {
                    String key = delivered.getSaleOrderId() + "-" + style.getStyleId() + "-" + sku.getSkuId();
                    BigDecimal quantity = delivereds.get(key);
                    if (quantity != null) quantity = quantity.add(sku.getQuantity());
                    else quantity = sku.getQuantity();
                    delivereds.put(key, quantity);
                }))
        );

        createdSaleOrders.forEach(created -> created.getStyles().forEach(style -> style.getSkus().forEach(
                sku -> {
                    String key = created.getSaleOrderId() + "-" + style.getStyleId() + "-" + sku.getSkuId();
                    BigDecimal modified = modifieds.getOrDefault(key, BigDecimal.ZERO);
                    BigDecimal delivered = delivereds.getOrDefault(key, BigDecimal.ZERO);
                    BigDecimal quantity = sku.getQuantity();
                    sku.setQuantity(quantity.add(modified).subtract(delivered));
                }))
        );

        return createdSaleOrders;
    }

    /**
     * 更新本单应付 ∑（sku开单数×sku开单单价 ± sku改欠货数×sku开单单价 -sku 退货数×sku退货单价） - 抹零金额 + ∑核进金额 - ∑核出金额
     *
     * @param saleOrderId 销售单ID
     */
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
    @Override
    public void updateAmountExpected(String saleOrderId) {
        // 开单总金额
        BigDecimal createGoodsAmount = createGoodsMapper.getCreateGoodsAmount(saleOrderId);
        // 改单总金额
        BigDecimal modifyGoodsAmount = modifyGoodsMapper.getModifyThatGoodsAmount(saleOrderId);
        // 退货总金额
        BigDecimal returnGoodsAmount = returnGoodsMapper.getReturnGoodsAmount(saleOrderId);
        // 抹零金额
        BigDecimal oddment = mapper.getOddment(saleOrderId);
        // 核进总金额
        BigDecimal clearanceInAmount = clearanceMapper.getClearanceInAmount(saleOrderId);
        // 核出总金额
        BigDecimal clearanceOutAmount = clearanceMapper.getClearanceOutAmount(saleOrderId);
        //∑（sku开单数×sku开单单价 ± sku改欠货数×sku开单单价 -sku 退货数×sku退货单价） - 抹零金额 + ∑核进金额 - ∑核出金额
        BigDecimal amountExpected = createGoodsAmount
                .add(modifyGoodsAmount)
                .subtract(returnGoodsAmount)
                .subtract(oddment)
                .add(clearanceInAmount)
                .subtract(clearanceOutAmount);
        // 更新
        mapper.updateAmountExpected(saleOrderId, amountExpected);
    }

    /**
     * 更新总收/退款 ∑（所有收/退款记录金额）
     *
     * @param saleOrderId 销售单ID
     */
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
    @Override
    public void updateAmountArrived(String saleOrderId) {
        BigDecimal amountArrived = remittanceMapper.getAmountArrivedOfSaleOrder(saleOrderId);
        mapper.updateAmountArrived(saleOrderId, amountArrived);
    }

    /**
     * 更新总核进/核出金额 ∑（核进/出金额）
     *
     * @param saleOrderId 销售单ID
     */
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
    @Override
    public void updateAmountCleared(String saleOrderId) {
        // 总核进金额
        BigDecimal amountClearedIn = clearanceMapper.getClearanceInAmount(saleOrderId);

        // 总核出金额
        BigDecimal amountClearedOut = clearanceMapper.getClearanceOutAmount(saleOrderId);
        // 总核进/核出金额
        BigDecimal amountCleared = amountClearedIn.subtract(amountClearedOut);
        // 更新
        mapper.updateAmountCleared(saleOrderId, amountCleared, amountClearedIn, amountClearedOut);
    }

    /**
     * 更新结欠金额∑（sku开单数×sku开单单价 ± sku改欠货数×sku开单单价 -sku 退货数×sku退货单价） - 抹零金额 + ∑核进金额 - ∑核出金额 - ∑收款账户收退款金额
     *
     * @param saleOrderId 销售单ID
     */
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
    @Override
    public void updateAmountRemain(String saleOrderId) {
        // 开单总金额
        BigDecimal createGoodsAmount = createGoodsMapper.getCreateGoodsAmount(saleOrderId);
        // 改单总金额
        BigDecimal modifyGoodsAmount = modifyGoodsMapper.getModifyThatGoodsAmount(saleOrderId);
        // 退货总金额
        BigDecimal returnGoodsAmount = returnGoodsMapper.getReturnGoodsAmount(saleOrderId);
        // 抹零金额
        BigDecimal oddment = mapper.getOddment(saleOrderId);
        // 核进总金额
        BigDecimal clearanceInAmount = clearanceMapper.getClearanceInAmount(saleOrderId);
        // 核出总金额
        BigDecimal clearanceOutAmount = clearanceMapper.getClearanceOutAmount(saleOrderId);
        // 总收退款金额
        BigDecimal amountArrived = remittanceMapper.getAmountArrivedOfSaleOrder(saleOrderId);
        //∑（sku开单数×sku开单单价 ± sku改欠货数×sku开单单价 -sku 退货数×sku退货单价） - 抹零金额 + ∑核进金额 - ∑核出金额
        BigDecimal amountRemain = createGoodsAmount
                .add(modifyGoodsAmount)
                .subtract(returnGoodsAmount)
                .subtract(oddment)
                .add(clearanceInAmount)
                .subtract(clearanceOutAmount)
                .subtract(amountArrived);
        // 更新
        mapper.updateAmountRemain(saleOrderId, amountRemain);
    }

    /**
     * 更新销售总数 ∑（sku开单数） ± ∑（sku改欠货数）
     *
     * @param saleOrderId 销售单ID
     */
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
    @Override
    public void updateTotalSold(String saleOrderId) {
        // 开单总数
        BigDecimal createGoodsTotal = createGoodsMapper.getCreateGoodsTotal(saleOrderId);
        // 改签货数
        BigDecimal modifyThatGoodsTotal = modifyGoodsMapper.getModifyThatGoodsTotal(saleOrderId);
        // 销售总数
        BigDecimal totalSold = createGoodsTotal.add(modifyThatGoodsTotal);
        // 更新
        mapper.updateTotalSold(saleOrderId, totalSold);
    }

    /**
     * 更新开单总数 ∑（sku开单数）
     *
     * @param saleOrderId 销售单ID
     */
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
    @Override
    public void updateTotalCreated(String saleOrderId) {
        BigDecimal totalCreated = createGoodsMapper.getCreateGoodsTotal(saleOrderId);
        mapper.updateTotalCreated(saleOrderId, totalCreated);
    }

    /**
     * 更新改他单总数 ∑（sku改欠货数）
     *
     * @param saleOrderId 销售单ID
     */
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
    @Override
    public void updateTotalModified(String saleOrderId) {
        BigDecimal totalModifiedInc = modifyGoodsMapper.getModifyThatGoodsTotalInc(saleOrderId);
        BigDecimal totalModifiedDec = modifyGoodsMapper.getModifyThatGoodsTotalDec(saleOrderId);
        BigDecimal totalModified = modifyGoodsMapper.getModifyThatGoodsTotal(saleOrderId);
        mapper.updateTotalModified(saleOrderId, totalModified, totalModifiedInc, totalModifiedDec);
    }

    /**
     * 更新退货总数 ∑（sku退货数）
     *
     * @param saleOrderId 销售单ID
     */
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
    @Override
    public void updateTotalReturned(String saleOrderId) {
        BigDecimal totalReturned = returnGoodsMapper.getReturnGoodsTotal(saleOrderId);
        mapper.updateTotalReturned(saleOrderId, totalReturned);
    }

    /**
     * 更新发货总数 ∑（发货sku）
     *
     * @param saleOrderId 销售单ID
     */
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
    @Override
    public void updateTotalDelivered(String saleOrderId) {
        BigDecimal totalDelivered = deliveryGoodsMapper.getDeliveryGoodsTotal(saleOrderId);
        mapper.updateTotalDelivered(saleOrderId, totalDelivered);
    }

    /**
     * 更新总欠货数 ∑（sku开单数） ± ∑（sku被改欠货数） - ∑（发货sku）
     *
     * @param saleOrderId 销售单ID
     */
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
    @Override
    public void updateTotalOwed(String saleOrderId) {
        // 开单总数
        BigDecimal totalCreated = createGoodsMapper.getCreateGoodsTotal(saleOrderId);
        // 改本单总数
        BigDecimal totalModified = modifyGoodsMapper.getModifyThisGoodsTotal(saleOrderId);
        // 发货总数
        BigDecimal totalDelivered = deliveryGoodsMapper.getDeliveryGoodsTotal(saleOrderId);
        // 欠货数
        BigDecimal totalOwed = totalCreated.add(totalModified).subtract(totalDelivered);
        // 更新
        mapper.updateTotalOwed(saleOrderId, totalOwed);
    }

    /**
     * 更新总开单金额 ∑(sku开单数×sku金额)
     *
     * @param saleOrderId 销售单ID
     */
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
    @Override
    public void updateAmountCreated(String saleOrderId) {
        BigDecimal amountCreated = createGoodsMapper.getCreateGoodsAmount(saleOrderId);
        mapper.updateAmountCreated(saleOrderId, amountCreated);
    }

    /**
     * 更新总改单金额 ∑(sku改欠货数×sku金额)
     *
     * @param saleOrderId 销售单ID
     */
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
    @Override
    public void updateAmountModified(String saleOrderId) {
        BigDecimal totalModified = modifyGoodsMapper.getModifyThatGoodsAmount(saleOrderId);
        mapper.updateAmountModified(saleOrderId, totalModified);
    }

    /**
     * 更新总退货金额 ∑(sku退货数×sku金额)
     *
     * @param saleOrderId 销售单ID
     */
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
    @Override
    public void updateAmountReturned(String saleOrderId) {
        BigDecimal amountReturned = returnGoodsMapper.getReturnGoodsAmount(saleOrderId);
        mapper.updateAmountReturned(saleOrderId, amountReturned);
    }

    /**
     * 查询销售单
     *
     * @param unitId          组织ID
     * @param startTime       开始时间
     * @param endTime         结束时间
     * @param userIds         用户ID
     * @param types           单据类型
     * @param saleOrderStatus 销售单状态
     * @param receiptStatus   收款单状态
     * @param startSearchTime 开始搜索时间
     * @param pageNo          页码
     * @param pageSize        每页最大数量
     * @return 销售单集合
     */
    @Override
    public List<SaleOrderQueryDTO> query(
            String unitId,
            String startTime,
            String endTime,
            List<String> userIds,
            List<SaleOrderType> types,
            List<SaleOrderQueryStatus> saleOrderStatus,
            List<ReceiptQueryStatus> receiptStatus,
            String startSearchTime,
            int pageNo,
            int pageSize
    ) {
        PageHelper.startPage(pageNo, pageSize);
        List<SaleOrderQueryDTO> orders = mapper.query(unitId, startTime, endTime, userIds, types, saleOrderStatus, receiptStatus, startSearchTime);
        if (orders == null || orders.isEmpty()) return Collections.emptyList();

        Map<String, SaleOrderQueryDTO> map = orders.stream().collect(Collectors.toMap(
                SaleOrderQueryDTO::getId,
                order -> order
        ));

        String[] saleOrderIds = map.keySet().toArray(new String[0]);

        List<SaleOrderQueryRemarkDTO> remarks = saleOrderRemarkMapper.getSaleOrderQueryRemarksIn(saleOrderIds);

        remarks.forEach(remark -> {
            SaleOrderQueryDTO order = map.get(remark.getSaleOrderId());
            if (order == null) return;
            order.getRemarks().add(remark);
        });

        saleOrderRemarkMapper.getSaleOrderQueryCreateGoodsRemarksIn(saleOrderIds).forEach(remark -> {
            SaleOrderQueryDTO order = map.get(remark.getSaleOrderId());
            if (order == null) return;
            order.getCreateGoodsRemarks().add(remark);
        });

        saleOrderRemarkMapper.getSaleOrderQueryReturnGoodsRemarksIn(saleOrderIds).forEach(remark -> {
            SaleOrderQueryDTO order = map.get(remark.getSaleOrderId());
            if (order == null) return;
            order.getReturnGoodsRemarks().add(remark);
        });

        return orders;
    }

    /**
     * 销售单详情
     *
     * @param saleOrderId 销售单ID
     * @return 销售单详情, 如果不存在则返回 {@code null}
     */
    @Override
    public SaleOrderDetailDTO detail(String saleOrderId) {
        // 获取详情
        SaleOrderDetailDTO detail = mapper.detail(saleOrderId);
        // 如果不存在 则直接返回 null
        if (detail == null) return null;

        {// 获取汇款记录列表
            List<SaleOrderDetailRemittanceDTO> remittances = remittanceMapper.getSaleOrderDetailRemittances(saleOrderId);
            detail.setRemittances(remittances);
        }

        {// 获取备注列表
            List<SaleOrderDetailRemarkDTO> remarks = saleOrderRemarkMapper.getSaleOrderDetailRemarks(saleOrderId);
            detail.setRemarks(remarks);
        }

        {// 获取核销记录列表
            List<SaleOrderDetailClearanceDTO> clearances = clearanceMapper.getSaleOrderDetailClearances(saleOrderId);
            detail.setClearances(clearances);
        }

        {// 获取改他单货品列表
            List<SaleOrderDetailModifyOrderDTO> orders = modifyGoodsMapper.getSaleOrderDetailModifyThatOrders(saleOrderId);
            orders.forEach(order -> order.getModifyGoods().forEach(goods -> {
                Optional<BigDecimal> inc = goods.getSkus().stream()
                        .filter(sku -> sku.getQuantity().compareTo(BigDecimal.ZERO) > 0)
                        .map(SaleOrderDetailModifyGoodsSKUDTO::getQuantity)
                        .reduce(BigDecimal::add);
                goods.setTotalModifiedInc(inc.orElse(BigDecimal.ZERO));

                Optional<BigDecimal> dec = goods.getSkus().stream()
                        .filter(sku -> sku.getQuantity().compareTo(BigDecimal.ZERO) < 0)
                        .map(SaleOrderDetailModifyGoodsSKUDTO::getQuantity)
                        .reduce(BigDecimal::add);
                goods.setTotalModifiedDec(dec.orElse(BigDecimal.ZERO));

                goods.setTotalModified(inc.orElse(BigDecimal.ZERO).add(dec.orElse(BigDecimal.ZERO)));

                Map<String, SaleOrderDetailModifyGoodsSKUDTO> map = goods.getSkus().stream().collect(Collectors.toMap(SaleOrderDetailModifyGoodsSKUDTO::getSkuId, sku -> sku));
                String thatOrderId = order.getSaleOrderId();
                String thatStyleId = goods.getStyleId();

                // 获取改他单货品的要货数
                CreateGoods create = createGoodsMapper.getSaleOrderCreateGoodsOfStyle(thatOrderId, thatStyleId);
                if (create == null) create = new CreateGoods();
                create.getSkus().forEach(sku -> {
                    SaleOrderDetailModifyGoodsSKUDTO SKU = map.get(sku.getSkuId());
                    if (SKU == null) return;
                    SKU.setQuantityCreated(sku.getQuantity());
                    goods.setTotalCreated(goods.getTotalCreated().add(sku.getQuantity()));
                });

                // 获取改他单货品的发货数
                List<DeliveryGoods> deliveries = deliveryGoodsMapper.getSaleOrderDeliveryGoodsOfStyle(thatOrderId, thatStyleId);
                deliveries.forEach(delivery -> delivery.getSkus().forEach(sku -> {
                    SaleOrderDetailModifyGoodsSKUDTO SKU = map.get(sku.getSkuId());
                    if (SKU == null) return;
                    SKU.setQuantityDelivered(sku.getQuantity());
                    goods.setTotalDelivered(goods.getTotalDelivered().add(sku.getQuantity()));
                }));
            }));
            detail.setModifyThatOrders(orders);
        }

//        {// 获取改本单货品列表
//            List<SaleOrderDetailModifyOrderDTO> orders = modifyGoodsMapper.getSaleOrderDetailModifyThisOrders(saleOrderId);
//            orders.forEach(order -> order.getModifyGoods().forEach(goods -> {
//                Optional<BigDecimal> inc = goods.getSkus().stream()
//                        .filter(sku -> sku.getQuantity().compareTo(BigDecimal.ZERO) > 0)
//                        .map(SaleOrderDetailModifyGoodsSKUDTO::getQuantity)
//                        .reduce(BigDecimal::add);
//                goods.setTotalModifiedInc(inc.orElse(BigDecimal.ZERO));
//
//                Optional<BigDecimal> dec = goods.getSkus().stream()
//                        .filter(sku -> sku.getQuantity().compareTo(BigDecimal.ZERO) < 0)
//                        .map(SaleOrderDetailModifyGoodsSKUDTO::getQuantity)
//                        .reduce(BigDecimal::add);
//                goods.setTotalModifiedDec(dec.orElse(BigDecimal.ZERO));
//
//                goods.setTotalModified(inc.orElse(BigDecimal.ZERO).add(dec.orElse(BigDecimal.ZERO)));
//            }));
//            detail.setModifyThisOrders(orders);
//        }

        {// 获取退货货品列表
            List<SaleOrderDetailReturnGoodsDTO> returnGoods = returnGoodsMapper.getSaleOrderDetailReturnGoods(saleOrderId);
            detail.setReturnGoods(returnGoods);

            // 退货货品备注
            Map<String, SaleOrderDetailReturnGoodsDTO> map = returnGoods.stream().collect(Collectors.toMap(SaleOrderDetailReturnGoodsDTO::getReturnGoodsId, goods -> goods));
            if (!map.isEmpty()) {
                List<SaleOrderDetailReturnGoodsRemarkDTO> remarks = returnGoodsRemarkMapper.getSaleOrderDetailReturnGoodsRemarksIn(map.keySet().toArray(new String[0]));
                remarks.forEach(remark -> {
                    SaleOrderDetailReturnGoodsDTO goods = map.get(remark.getReturnGoodsId());
                    goods.getRemarks().add(remark);
                });
            }
        }

        { // 获取开单要货列表
            List<SaleOrderDetailCreateGoodsDTO> createGoods = createGoodsMapper.getSaleOrderDetailCreateGoods(saleOrderId);
            detail.setCreateGoods(createGoods);

            {// 获取被改欠货列表
                List<SaleOrderDetailModifyGoodsDTO> modifyGoods = modifyGoodsMapper.getSaleOrderDetailModifyThisGoods(saleOrderId);
                Map<String, SaleOrderDetailCreateGoodsDTO> map = createGoods.stream().collect(Collectors.toMap(SaleOrderDetailCreateGoodsDTO::getStyleId, goods -> goods));
                modifyGoods.forEach(modify -> {
                    SaleOrderDetailCreateGoodsDTO create = map.get(modify.getStyleId());
                    if (create == null) return;
                    Map<String, SaleOrderDetailCreateGoodsSKUDTO> m = create.getSkus().stream().collect(Collectors.toMap(SaleOrderDetailCreateGoodsSKUDTO::getSkuId, sku -> sku));
                    List<SaleOrderDetailModifyGoodsSKUDTO> skus = modify.getSkus();
                    skus.forEach(sku -> {
                        create.setTotalModified(create.getTotalModified().add(sku.getQuantity()));
                        SaleOrderDetailCreateGoodsSKUDTO SKU = m.get(sku.getSkuId());
                        if (SKU == null) return;
                        BigDecimal quantity = SKU.getQuantityModified();
                        if (quantity == null) SKU.setQuantityModified(sku.getQuantity());
                        else SKU.setQuantityModified(quantity.add(sku.getQuantity()));
                    });
                });
            }

            {// 获取发货货品列表
                List<SaleOrderDetailDeliveryGoodsDTO> deliveryGoods = deliveryGoodsMapper.getSaleOrderDetailDeliveryGoods(saleOrderId);
                Map<String, SaleOrderDetailCreateGoodsDTO> map = createGoods.stream().collect(Collectors.toMap(SaleOrderDetailCreateGoodsDTO::getStyleId, goods -> goods));
                deliveryGoods.forEach(delivery -> {
                    SaleOrderDetailCreateGoodsDTO create = map.get(delivery.getStyleId());
                    if (create == null) return;
                    Map<String, SaleOrderDetailCreateGoodsSKUDTO> m = create.getSkus().stream().collect(Collectors.toMap(SaleOrderDetailCreateGoodsSKUDTO::getSkuId, sku -> sku));
                    List<SaleOrderDetailDeliveryGoodsSKUDTO> skus = delivery.getSkus();
                    skus.forEach(sku -> {
                        SaleOrderDetailCreateGoodsSKUDTO SKU = m.get(sku.getSkuId());
                        if (SKU == null) return;
                        BigDecimal quantity = SKU.getQuantityModified();
                        if (quantity == null) SKU.setQuantityModified(sku.getQuantity());
                        else SKU.setQuantityModified(quantity.add(sku.getQuantity()));
                    });
                });
            }

            {// 计算欠货数
                createGoods.forEach(goods -> goods.getSkus().forEach(sku -> {
                    BigDecimal quantityCreated = sku.getQuantityCreated();
                    BigDecimal quantityModified = sku.getQuantityModified();
                    BigDecimal quantityDelivered = sku.getQuantityDelivered();
                    BigDecimal quantityOwed = quantityCreated.add(quantityModified).subtract(quantityDelivered);
                    sku.setQuantityOwed(quantityOwed);
                }));
            }

            {// 开单要货货品备注
                Map<String, SaleOrderDetailCreateGoodsDTO> map = createGoods.stream().collect(Collectors.toMap(SaleOrderDetailCreateGoodsDTO::getCreateGoodsId, goods -> goods));
                if (!map.isEmpty()) {
                    List<SaleOrderDetailCreateGoodsRemarkDTO> remarks = createGoodsRemarkMapper.getSaleOrderDetailCreateGoodsRemarksIn(map.keySet().toArray(new String[0]));
                    remarks.forEach(remark -> {
                        SaleOrderDetailCreateGoodsDTO goods = map.get(remark.getCreateGoodsId());
                        goods.getRemarks().add(remark);
                    });
                }
            }
        }

        return detail;
    }

    /**
     * 获取销售单抹零金额
     *
     * @param saleOrderId 销售单ID
     * @return 销售单抹零金额
     */
    @Override
    public BigDecimal getSaleOrderOddment(String saleOrderId) {
        return mapper.getOddment(saleOrderId);
    }

    /**
     * 设置销售单的抹零金额
     *
     * @param saleOrderId 销售单ID
     * @param oddment     抹零金额
     */
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
    @Override
    public void setOddment(String saleOrderId, BigDecimal oddment) {
        mapper.setOddment(saleOrderId, oddment);
    }

    /**
     * 撤销销售单
     *
     * @param saleOrderId 销售单ID
     */
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
    @Override
    public void cancel(String saleOrderId) {
        mapper.cancel(saleOrderId);
    }

    /**
     * 查询可核销的销售单列表
     *
     * @param unitId          组织ID
     * @param startSearchTime 开始搜索时间
     * @param pageNo          页码
     * @param pageSize        每页最大条数
     * @return 可核销的销售单列表
     */
    @Override
    public List<SaleOrderQueryDTO> clearables(String unitId, String customerId, String startSearchTime, int pageNo, int pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        return mapper.clearables(unitId, customerId, startSearchTime);
    }
}